package com.group2.operations.service.impl;

import com.group2.operations.mapper.FlowMapper;
import com.group2.operations.model.ProcessState;
import com.group2.operations.service.FlowService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FlowServiceImpl implements FlowService{
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FlowMapper flowMapper;

    /**
     * 开启流程
     * @param variables 传递变量
     * @param processId 流程ID
     * @return Process实例
     */
    @Override
    @Transactional
    public ProcessInstance startProcess(Map<String, Object> variables, String processId) {
        ProcessInstance process = runtimeService.startProcessInstanceByKey(processId, variables);
        //获取创建好的流程ID
        String id = process.getId();
        //向数据库中插入流程状态
        flowMapper.insertFlowState(id, "流程建立", new Date());

        return process;
    }

    /**
     * 根据用户名查询流程实例
     * @param username 用户名
     * @return 流程实例列表
     */
    @Override
    public List<HistoricProcessInstance> queryProcessByUserName(String username) {
        return historyService.createHistoricProcessInstanceQuery()
                .startedBy(username)
                .orderByProcessInstanceStartTime()
                .desc()
                .list();
    }

    /**
     * 完成流程的第一个任务
     * @param username 用户名
     * @param taskName 任务名
     * @param processId 流程ID
     * @param processName 流程名
     * @param startTime 开始时间
     */
    @Override
    public void completeFirstTask(String username, String taskName, String processId, String processName, Date startTime) {
        List<Task> tasks = taskService.createTaskQuery()
                .taskAssignee(username)
                .list();
        //把processId加入流程变量
        Map<String, Object> map = new HashMap<>();
        map.put("processId", processId);
        map.put("startTime", startTime);
        map.put("processName", processName);
        for(Task task : tasks) {
            if(taskName.equals(task.getName())) {
                taskService.complete(task.getId(), map);
            }
        }
    }

    /**
     * 判断一个流程是否完成
     * @param processId
     * @return
     */
    @Override
    public boolean isFinished(String processId) {
        return historyService.createHistoricProcessInstanceQuery()
                .finished()
                .processInstanceId(processId)
                .count() > 0;
    }

    /**
     * 获取一个流程经历的所有事件
     * @param processId 流程ID
     * @return
     */
    @Override
    public ProcessState getHistory(String processId) {
        return flowMapper.queryHistoryByProcessId(processId);
    }

    /**
     * 判断一个用户是否已发起申请代理商流程
     * @param username 用户名
     * @return
     */
    @Override
    public boolean hasApplied(String username) {
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
                .startedBy(username)
                .list();
        if(list.size() == 0) {
            return false;
        }
        for(ProcessInstance process : list) {
            if("代理商申请流程".equals(process.getProcessDefinitionName())) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean haAppliedToChangeState(String username, int sid) {
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
                .includeProcessVariables()
                .startedBy(username)
                .list();
        if(list.size() == 0) {
            return false;
        }
        Map<String, Object> variables = null;
        String processName = null;
        int id = 0;
        for(ProcessInstance process : list) {
            variables = process.getProcessVariables();
            processName = (String) variables.get("processName");
            if(variables.containsKey("sid")) {
                id = (int) variables.get("sid");
            }
            if(id == sid && "改变厅店状态".equals(processName)) {
                return true;
            }
        }
        return false;
    }
}
